
#include "html/html.h"
#include <Arduino.h>

// #include <LittleFS.h>
#ifdef ESP8266
#include <ESP8266WebServer.h>
ESP8266WebServer web_server(80);
#elif ESP32
#include <Update.h>
#include <WebServer.h>
WebServer web_server(80);
#endif
#include "eeprom_.h"
String update_result = "err";
extern void open_relay();
extern void close_relay();
extern void rst();
extern void time_task_init();
extern String read_state();
void index_handler()
{
  web_server.sendHeader("Cache-control", "no-cache");
  web_server.sendHeader("Content-Encoding", "gzip");
  web_server.setContentLength(INDEX_LEN);
#ifdef ESP8266
  web_server.send(200, "text/html; charset=utf-8", (char *)index_html, INDEX_LEN);
#elif ESP32
  web_server.send(200, "text/html; charset=utf-8", String((char *)index_html, INDEX_LEN));
#endif
}
void config_handler()
{
  web_server.sendHeader("Cache-control", "no-cache");
  web_server.sendHeader("Content-Encoding", "gzip");
  web_server.setContentLength(CONFIG_LEN);
#ifdef ESP8266
  web_server.send(200, "text/html; charset=utf-8", (char *)config_html, INDEX_LEN);
#elif ESP32
  web_server.send(200, "text/html; charset=utf-8", String((char *)config_html, CONFIG_LEN));
#endif
}
void update_handler()
{
  web_server.sendHeader("Cache-Control", "no-cache");
  web_server.sendHeader("Content-Encoding", "gzip");
  web_server.setContentLength(UPDATE_LEN);
#ifdef ESP8266
  web_server.send(200, "text/html; charset=utf-8", (char *)update_html);
#elif ESP32
  web_server.send(200, "text/html; charset=utf-8", String((char *)update_html, UPDATE_LEN));
#endif
}
void scan_handler()
{ // wifi扫描
#ifdef ESP32
  disableCore0WDT();
#endif
  int n = WiFi.scanNetworks();
#ifdef ESP32
  enableCore0WDT();
#endif
  String json = "{\"wifi_arr\":[";
  for (int i = 0; i < n; ++i)
  {
    json += ("{\"ssid\":\"" + WiFi.SSID(i) + "\",");
    json += ("\"rssi\":\"(" + String(WiFi.RSSI(i)) + "dB)\"},");
  }
  json = json.substring(0, json.length() - 1);
  json += "]}";
  web_server.send(200, "application/json", json);
}
void save_wifi_handler()
{
  // LEN2个参数全部存入数组
  for (int i = 0; i < LEN2; i++)
  {
    String arg = web_server.urlDecode(web_server.arg(i));
    // 密码或密钥如果全为*则不保存
    if ((i == PASS_INDEX || i == BLINKER_AUTH_INDEX || i == BEMFA_AUTH_INDEX) && (arg.length() > 0))
    {
      bool is_not_changed = true;
      for (int j = 0; j < arg.length(); j++)
      {
        if (arg.charAt(i) != '*')
        {
          is_not_changed = false;
          break;
        }
      }
      if (is_not_changed)
      {
        continue;
      }
    }
    mempcpy((save_data + (LEN1 * INT_LEN) + (i * STR_LEN)), arg.c_str(), arg.length() + 1);
  }
  eeprom_write();
  web_server.send(200, "application/json; charset=utf-8", "{\"result\":\"ok\"}");
}
void config_data_get()
{
  String json = "{";
  for (int i = 0; i < LEN2; i++)
  {
    String value = String((char *)(save_data + (LEN1 * INT_LEN) + (i * STR_LEN)));
    // 密码或密钥换成*显示
    int value_len = value.length();
    if ((i == PASS_INDEX || i == BLINKER_AUTH_INDEX || i == BEMFA_AUTH_INDEX) && (value_len > 0))
    {
      value = "*";
      for (int j = 0; j < value_len; j++)
      {
        value += "*";
      }
    }
    json += "\"arg" + String(i) + "\":\"" + value;
    if (i != LEN2 - 1)
    {
      json += "\",";
    }
    else
    {
      json += "\"}";
    }
  }
  web_server.send(200, "application/json; charset=utf-8", json);
}
void reboot_handler()
{
  web_server.send(200, "application/json; charset=utf-8", "{\"result\":\"ok\"}");
  delay(1000);
#ifdef ESP8266
  ESP.restart();
#elif ESP32
  esp_restart();
#endif
}
void relay_set_handler()
{
  String arg0_name = web_server.argName(0);
  String arg0_value = web_server.arg(0);
  if (arg0_value.compareTo("open") == 0)
  {
    open_relay();
  }
  else if (arg0_value.compareTo("close") == 0)
  {
    close_relay();
  }
  web_server.send(200, "application/json; charset=utf-8", "{\"result\":\"ok\"}");
}
void data_get_handler()
{
  String json = "{";
  for (int i = 0; i < LEN1; i++)
  {
    String value = String(*((int *)(save_data + (i * INT_LEN))));
    json += "\"arg" + String(i) + "\":\"" + value + "\",";
  }
  json += "\"state\":\"" + read_state() + "\",";
  json += "\"serverip\":\"" + WiFi.localIP().toString() + "\"}";
  web_server.send(200, "application/json; charset=utf-8", json);
}
void not_found_handler()
{
  web_server.send(404, "text/html", "404");
}
void time_task_handler()
{
  // LEN1个参数全部存入数组
  for (int i = 0; i < LEN1; i++)
  {
    int arg = web_server.arg(i).toInt();
    memcpy(save_data + (i * INT_LEN), (unsigned char *)(&arg), INT_LEN);
  }

  eeprom_write();
  time_task_init();
  web_server.send(200, "application/json; charset=utf-8", "{\"result\":\"ok\"}");
}
void update_end_handler()
{
  if (update_result.compareTo("ok") == 0)
  {
    eeprom_clear(); // 清除数据
    web_server.send(200, "application/json; charset=utf-8", "{\"result\":\"ok\"}");
    delay(3000);
#ifdef ESP32
    esp_restart();
#endif
  }
  else
  {
    web_server.send(200, "application/json; charset=utf-8", "{\"result\":\"err\"}");
  }
}
void update_start_handler()
{
  HTTPUpload &upload = web_server.upload();
  if (upload.status == UPLOAD_FILE_START)
  {
    update_result = "err";
    Serial.printf("Update filename: %s\n", upload.filename.c_str());
    if (!Update.begin(1920 * 1024))
    { // start with max available size
      Update.printError(Serial);
    }
  }
  else if (upload.status == UPLOAD_FILE_WRITE)
  {
    Serial.printf("Update write: %d\n", upload.currentSize);
    /* flashing firmware to ESP*/
    if (Update.write(upload.buf, upload.currentSize) != upload.currentSize)
    {
      Update.printError(Serial);
    }
  }
  else if (upload.status == UPLOAD_FILE_END)
  {
    if (Update.write(upload.buf, upload.currentSize) != upload.currentSize)
    {
      Update.printError(Serial);
    }
    if (Update.end(true))
    {
      update_result = "ok";
      Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
    }
    else
    {
      Update.printError(Serial);
    }
  }
}
void rst_handler()
{
  rst();
  web_server.send(200, "application/json; charset=utf-8", "{\"result\":\"ok\"}");
}
void web_server_setup()
{
  // index
  web_server.on("/", HTTP_GET, index_handler);
  web_server.on("/relay_set", HTTP_GET, relay_set_handler);
  web_server.on("/data_get", HTTP_GET, data_get_handler);
  web_server.on("/time_task", HTTP_GET, time_task_handler);
  web_server.on("/rst", HTTP_GET, rst_handler);
  // config
  web_server.on("/config", HTTP_GET, config_handler);
  web_server.on("/scan", HTTP_GET, scan_handler);
  web_server.on("/save_wifi", HTTP_GET, save_wifi_handler);
  web_server.on("/config_data_get", HTTP_GET, config_data_get);
  web_server.on("/reboot", HTTP_GET, reboot_handler);
  // update
#ifdef ESP32
  web_server.on("/update", HTTP_GET, update_handler);
  web_server.on("/update_start", HTTP_POST, update_end_handler, update_start_handler);
#endif
  // 404
  web_server.onNotFound(not_found_handler);
  web_server.begin();
}
void web_server_loop() { web_server.handleClient(); }